using System;
using System.Net;
using CodePlex.TfsLibrary.RepositoryWebSvc;
using Xunit;

namespace CodePlex.TfsLibrary.ClientEngine
{
    public class TfsEngineQueryItemsTest
    {
        [Fact]
        public void CallsBackForCredentialsOnStartup()
        {
            NetworkCredential creds = new NetworkCredential("joe", "bob");
            TestableTfsEngine engine = TestableTfsEngine.Create();
            engine.CredentialsCallback = delegate
                                         {
                                             Assert.False(engine.SourceControlService.QueryItems__Called);
                                             return creds;
                                         };

            engine.QueryItems("http://tfsUrl", "$/Foo", RecursionType.Full, VersionSpec.Latest);

            Assert.True(engine.SourceControlService.QueryItems__Called);
            Assert.Same(creds, engine.SourceControlService.QueryItems_Credentials);
        }

        [Fact]
        public void FailWithNoCallback()
        {
            TestableTfsEngine engine = TestableTfsEngine.Create();
            engine.SourceControlService.QueryItems__ThrowsCredExceptionOnce = true;

            Assert.Throws<NetworkAccessDeniedException>(delegate
                                                        {
                                                            engine.QueryItems("http://tfsUrl",
                                                                              "$/ServerPath",
                                                                              RecursionType.Full,
                                                                              VersionSpec.Latest);
                                                        });
        }

        [Fact]
        public void QueryItemsFailure()
        {
            ICredentials outCreds = null;
            string callbackTfsUrl = null;
            TestableTfsEngine engine = TestableTfsEngine.Create();
            engine.SourceControlService.QueryItems__ThrowsCredExceptionOnce = true;
            engine.CredentialsCallback = delegate(ICredentials oldCredentials,
                                                  string tfsUrl)
                                         {
                                             callbackTfsUrl = tfsUrl;
                                             return null;
                                         };

            try
            {
                engine.QueryItems("http://tfsUrl", "$/Foo", RecursionType.Full, VersionSpec.Latest);
                throw new InvalidOperationException("Expected a throw!");
            }
            catch (NetworkAccessDeniedException) {}

            Assert.Equal("http://tfsUrl", callbackTfsUrl);
            Assert.Null(outCreds);
        }

        [Fact]
        public void Retried()
        {
            NetworkCredential creds = new NetworkCredential("jim", "jeff");
            string callbackTfsUrl = null;
            TestableTfsEngine engine = TestableTfsEngine.Create();
            engine.SourceControlService.QueryItems__ThrowsCredExceptionOnce = true;
            engine.CredentialsCallback = delegate(ICredentials oldCredentials,
                                                  string tfsUrl)
                                         {
                                             callbackTfsUrl = tfsUrl;
                                             return creds;
                                         };

            engine.QueryItems("http://tfsUrl", "$/Foo", RecursionType.Full, VersionSpec.Latest);

            Assert.Equal("http://tfsUrl", callbackTfsUrl);
            Assert.Same(creds, engine.SourceControlService.QueryItems_Credentials);
        }
    }
}